﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Company.Core.Helper;
using Company.Hardware;
using Company.Sqlite.Interfaces;
using Company.Sqlite.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Configuration;
using System.Web.UI.WebControls;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Threading;
using 无人值守地磅称重系统.Enums;
using 无人值守地磅称重系统.Extentions;
using 无人值守地磅称重系统.Interfaces;
using CompanyEntiey = Company.Sqlite.Models.Company;

namespace 无人值守地磅称重系统.ViewModels
{
    internal class IndexViewModel : ObservableObject
    {
        private double triggerScaleValue;
        public double TriggerScaleValue { get => triggerScaleValue; set => SetProperty(ref triggerScaleValue, value);}

        private List<Data> tempDataList = new List<Data>();
        public List<Data> TempDataList { get => tempDataList; set => SetProperty(ref tempDataList, value); }

        private List<Data> dataList = new List<Data>();
        public List<Data> DataList { get => dataList; set => SetProperty(ref dataList, value); }

        private ScaleMode scaleMode = ScaleMode.无;
        public ScaleMode ScaleMode { get=>scaleMode; set=>SetProperty(ref scaleMode,value); }

        private string transportMode = "发货";

        private Data currentData = new Data();
        /// <summary>
        /// 等待保存数据
        /// </summary>
        public Data CurrentData { get => currentData; set => SetProperty(ref currentData, value); }

        private Car currentCar = new Car();
        public Car CurrentCar { get => currentCar; set => SetProperty(ref currentCar, value); }

        private List<Car> cars= new List<Car>();
        public List<Car> Cars { get => cars; set => SetProperty(ref cars, value); }

        private Stuff currentStuff = new Stuff();
        public Stuff CurrentStuff { get => currentStuff; set => SetProperty(ref currentStuff, value); }

        private List<Stuff> stuffs = new List<Stuff>();
        public List<Stuff> Stuffs { get => stuffs; set => SetProperty(ref stuffs, value); }

        private CompanyEntiey currentReceiveCompany = new CompanyEntiey();
        public CompanyEntiey CurrentReceiveCompany { get => currentReceiveCompany; set => SetProperty(ref currentReceiveCompany, value); }

        private CompanyEntiey currentSendCompany = new CompanyEntiey();
        public CompanyEntiey CurrentSendCompany { get => currentSendCompany; set => SetProperty(ref currentSendCompany, value); }

        private CompanyEntiey currentTransportCompany = new CompanyEntiey();
        public CompanyEntiey CurrentTransportCompany { get => currentTransportCompany; set => SetProperty(ref currentTransportCompany, value); }

        private List<CompanyEntiey> companies = new List<CompanyEntiey>();
        public List<CompanyEntiey> Companies { get => companies; set => SetProperty(ref companies, value); }

        public ICommand SelectTransportModeCommand { get; }
        public ICommand LoadCommand { get; }

        // 按钮操作命令
        public ICommand ClearCommand { get; }
        public ICommand ScaleByPweightCommand { get; }
        public ICommand ScalePweightCommand { get; }
        public ICommand ScaleMweightCommand { get; }
        public ICommand ScaleByAutoCommand { get; }
        public ICommand SaveCommand { get; }
        public ICommand TriggerCameraCommand { get; }
        public ICommand TriggerScaleCommand { get; }
        public ICommand ContinueScaleCommand { get; }


        public ISession Session { get; }

        public ICamera Camera { get; }

        public IScale Scale { get; }

        public IHardwareManager HardwareManager { get; }

        public ICarRepository CarRepository { get; }
        public IStuffRepository StuffRepository { get; }
        public ICompanyRepository CompanyRepository { get; }
        public IDataRepository DataRepository { get; }
        public IConfigService ConfigService { get; }
        public IPrintService PrintService { get; }

        public IndexViewModel(ISession session,
            ICamera camera,
            IScale scale,
            IHardwareManager hardwareManager,
            ICarRepository carRepository,
            IStuffRepository stuffRepository,
            ICompanyRepository companyRepository,
            IDataRepository dataRepository,
            IConfigService configService,
            IPrintService printService)
        {
            Session = session;
            Camera = camera;
            HardwareManager = hardwareManager;
            Scale = scale;
            CarRepository = carRepository;
            StuffRepository = stuffRepository;
            CompanyRepository = companyRepository;
            DataRepository = dataRepository;
            ConfigService = configService;
            PrintService = printService;

            Refresh();

            SelectTransportModeCommand = new RelayCommand<string>(SelectTransportMode);
            LoadCommand = new RelayCommand(Load);
            ClearCommand = new RelayCommand(Clear);
            ScaleByPweightCommand = new RelayCommand(ScaleByPweight);
            ScalePweightCommand = new RelayCommand(ScalePweight);
            ScaleMweightCommand = new RelayCommand(ScaleMweight);
            ScaleByAutoCommand = new RelayCommand(ScaleByAuto);
            SaveCommand = new AsyncRelayCommand(SaveAsync);
            TriggerCameraCommand = new RelayCommand<string>(TriggerCamera);
            TriggerScaleCommand = new RelayCommand(TriggerScale);
            ContinueScaleCommand = new RelayCommand<Data>(ContinueScale);

          

            Camera.ValueChanged += Camera_ValueChanged;

            Task.Factory.StartNew(ScaleJob);
        }

        /// <summary>
        /// 二次称重
        /// </summary>
        /// <param name="obj"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void ContinueScale(Data data)
        {
            if (ScaleMode == ScaleMode.自动称重)
                return;
            if (data == null || data.CarName != Camera.Value)
            {
                Session.Show("车牌号不一致");
                return;
            }
            if (data.Mweight == 0)
            {
                ScaleMode = ScaleMode.毛重;
            }
            if (data.Pweight == 0)
            {
                ScaleMode = ScaleMode.皮重;
            }
            else
            {
                return;
            }

            CurrentData = data;
            CurrentReceiveCompany = companies.FirstOrDefault(t => t.Id == CurrentData.ReceiveCompanyId);
            CurrentSendCompany = companies.FirstOrDefault(t => t.Id == CurrentData.SendCompanyId);
            CurrentTransportCompany = companies.FirstOrDefault(t => t.Id == CurrentData.TransportCompanyId);
        }

        private void ScaleJob()
        {
            while (true)
            {
                switch (ScaleMode)
                {
                    case ScaleMode.无:
                        break;
                    case ScaleMode.皮重:
                        CurrentData.Pweight = Scale.Value;
                        break;
                    case ScaleMode.毛重:
                        CurrentData.Mweight = Scale.Value;
                        break;
                    case ScaleMode.手动置皮:
                        CurrentData.Mweight = Scale.Value;
                        break;
                    case ScaleMode.自动称重:
                        break;
                    case ScaleMode.测试:
                        break;
                    default:
                        break;
                }

                CurrentData.CalcJweight();
                CurrentData.CalcSumPrice();
                
                Task.Delay(50).Wait();
            }
        }

        private void TriggerScale()
        {
            Scale.Trigger(TriggerScaleValue);
        }

        private void Camera_ValueChanged(string carName)
        {
            currentData.CarName = carName;
            if(ScaleMode == ScaleMode.自动称重)
            {
                AutoScale();
            }
        }

        /// <summary>
        /// 自动过磅
        /// </summary>
        private void AutoScale()
        {
            // 假设应用场景：先称皮重，后称毛重
            if (Scale.Value <= 0)
                return;
            // 家庭作业：在这里等一段时间，判断当前仪表的值是否稳定

            // 仪表稳定后，开始自动称重业务
            var temp = TempDataList.FirstOrDefault(t => t.CarName == currentData.CarName);
            if(temp != null)
            {
                // 称毛重
                temp.Mweight = Scale.Value;
                temp.Mdate = DateTime.Now;
                temp.CalcJweight();
                temp.CalcSumPrice();
                int count = DataRepository.Update(temp);
                if(count <= 0)
                {
                    Log.Error($"在自动称毛重时，{temp.Id}, {temp.CarName},重量：{temp.Mweight},更新失败！");
                }
                // 打印磅单
                if (ConfigService.SystemConfig.IsPrint)
                {
                    PrintService.Print(temp.DeepClone(), ConfigService.SystemConfig.IsPreview);
                }
            }
            else
            {
                // 称皮重
                Data data = new Data();
                data.Pweight = Scale.Value;
                data.Pdate= DateTime.Now;
                data.CarName = currentData.CarName;
                data.StuffName = CurrentData.StuffName??"物资";
                data.UserId = CurrentData.UserId;
                data.UserName = CurrentData.CarName;
                data.ScaleMode = (int)ScaleMode;
                data.TransportMode = transportMode;

                // 收发运公司数据
                if (CurrentReceiveCompany != null)
                {
                    data.ReceiveCompanyId = CurrentReceiveCompany.Id;
                    data.ReceiveCompanyName = CurrentReceiveCompany.Name;
                }
                if (CurrentSendCompany != null)
                {
                    data.SendCompanyId = CurrentSendCompany.Id;
                    data.SendCompanyName = CurrentSendCompany.Name;
                }
                if (CurrentTransportCompany != null)
                {
                    data.TransportCompanyId = CurrentTransportCompany.Id;
                    data.TransportCompanyName = CurrentTransportCompany.Name;
                }

                Validate(data);
                int count = DataRepository.Insert(data);
                if(count <= 0)
                {
                    Log.Error($"在自动称皮重时，{temp.Id},{temp.CarName},重量：{temp.Pweight},插入失败！");
                }
            }
            Refresh();
        }

        private void TriggerCamera(string carName)
        {
            Camera.Trigger(carName);
        }

        private async Task SaveAsync()
        {
            var t = Task.Factory.StartNew( (e) => {
                if (!(e is Data data))
                    return;
                if (!(ScaleMode == ScaleMode.手动置皮 || ScaleMode == ScaleMode.毛重 || ScaleMode == ScaleMode.皮重))
                    return;
                if (string.IsNullOrEmpty(data.CarName))
                {
                    Session.Show("车牌号不能为空");
                    return;
                }
                if (string.IsNullOrEmpty(data.StuffName))
                {
                    Session.Show("物资不能为空");
                }
                if(ScaleMode == ScaleMode.手动置皮 &&　data.Pweight <= 0)
                {
                    Session.Show("请输入皮重");
                }
                // 验证车牌号、物资
                Validate(data);
                //填充数据
                Adapter(data);
                // 保存数据
                Save(data);
                // 刷新
                Refresh();

            }, CurrentData.Id == 0 ? CurrentData.DeepClone() : CurrentData);
            await t;
        }

        private void Refresh()
        {
            TempDataList = DataRepository.GetAllTemp();
            DataList = DataRepository.GetAllToday();
            DoClear();
        }

        /// <summary>
        /// 新增或修改数据
        /// </summary>
        /// <param name="data"></param>
        private void Save(Data data)
        {
            if(data.Id == 0)
            {
                int count = DataRepository.Insert(data);
                if(count <= 0)
                {
                    Log.Error($"{data.CarName}, {data.StuffName}, {data.Mweight}, {data.Pweight}, 添加失败！");
                }
            }
            else
            {
                int count = DataRepository.Update(data);
                if (count <= 0)
                {
                    Log.Error($"{data.CarName}, {data.StuffName}, {data.Mweight}, {data.Pweight}, 添加失败！");
                }
            }

            //磅单打印
            if (data.Mdate != null && data.Pdate != null)
            {
                if (ConfigService.SystemConfig.IsPrint)
                {
                    PrintService.Print(data.DeepClone(), ConfigService.SystemConfig.IsPreview);
                }
            }
        }

        private void Adapter(Data data)
        {
            if (data == null)
                return;
            data.UserId = Session.CurrentUser.Id;
            data.UserName = Session.CurrentUser.UserName;
            data.ScaleMode = (int)ScaleMode;
            data.TransportMode = transportMode;

            // 收发运公司数据
            if(CurrentReceiveCompany != null)
            {
                data.ReceiveCompanyId = CurrentReceiveCompany.Id;
                data.ReceiveCompanyName = CurrentReceiveCompany.Name;
            }
            if(CurrentSendCompany != null)
            {
                data.SendCompanyId = CurrentSendCompany.Id;
                data.SendCompanyName = CurrentSendCompany.Name;
            }
            if(CurrentTransportCompany != null)
            {
                data.TransportCompanyId = CurrentTransportCompany.Id;
                data.TransportCompanyName = CurrentTransportCompany.Name;
            }

        }

        /// <summary>
        /// 验证数据
        /// </summary>
        /// <param name="data"></param>
        /// <exception cref="Exception"></exception>
        private void Validate(Data data)
        {
            // 优先使用数据库中的车牌号
            var car = CarRepository.Select(data.CarName);
            if(car == null)
            {
                Car entity = new Car();
                entity.Name = data.CarName;
                int count = CarRepository.Insert(entity);
                if (count > 0)
                {
                    data.CarId = entity.Id;
                }
                else
                {
                    throw new Exception("自动添加车牌失败");
                }
            }
            else
            {
                data.CarId = car.Id;
            }

            // 优先使用数据库中的物资
            var stuff = StuffRepository.Select(data.StuffName);
            if (stuff == null)
            {
                Stuff entity = new Stuff();
                entity.Name = data.StuffName;
                int count = StuffRepository.Insert(entity);
                if (count > 0)
                {
                    data.StuffId = entity.Id;
                }
                else
                {
                    throw new Exception("自动添加物资失败");
                }
            }
            else
            {
                data.StuffId = stuff.Id;
            }

            switch (ScaleMode)
            {
                case ScaleMode.无:
                    break;
                case ScaleMode.皮重:
                    data.Pdate = DateTime.Now;
                    break;
                case ScaleMode.毛重:
                    data.Mdate = DateTime.Now;
                    break;
                case ScaleMode.手动置皮:
                    data.Pdate = DateTime.Now;
                    data.Mdate = DateTime.Now;
                    break;
                case ScaleMode.自动称重:
                    break;
                case ScaleMode.测试:
                    data.Pdate = DateTime.Now;
                    data.Mdate = DateTime.Now;
                    break;
                default:
                    break;
            }
        }

        private void ScaleByAuto()
        {
            DoClear();
            ScaleMode = ScaleMode.自动称重;
        }

        private void ScaleMweight()
        {
            DoClear();
            ScaleMode = ScaleMode.毛重;
        }

        private void ScalePweight()
        {
            DoClear();
            ScaleMode = ScaleMode.皮重;
        }

        private void ScaleByPweight()
        {
            DoClear();
            ScaleMode = ScaleMode.手动置皮;
        }

        private void Clear()
        {
            DoClear();
            ScaleMode = ScaleMode.无;
        }

        private void DoClear() => CurrentData = new Data();


        private void Load()
        {
            Cars = CarRepository.GetAll();
            Stuffs = StuffRepository.GetAll();
            Companies = CompanyRepository.GetAll();
        }

        private void SelectTransportMode(string mode)
        {
            transportMode= mode;
        }
    }
}
